'use strict'

/**
 * Web访问相关
 */
//------------------------------------------------------------------
import axios from 'axios'
import utils from '../utils'
//------------------------------------------------------------------

export default class Axios {
    __axios
    constructor(opt) {
        this.__error = opt.error
        this.__notLogin = opt.notLogin
        this.__axios = axios.create({
            baseURL: import.meta.env.VITE_APP_API_URL,
            timeout: import.meta.env.VITE_APP_API_TIMEOUT
        })
    }

    /**
     * 请求拦截器
     *
     * @param config 数据
     * @param opts 配置
     * @param callback 回调函数
     */
    async __request(config, opts, callback) {
        if (opts.need_token) {
            let token = utils.getStorage('token') ?? ''
            if (!token) {
                return callback({ headers: {}, data: { status: 401, code: 'not_login', msg: '没有登陆!' } })
            }
            Object.assign(config.headers, { vt: token })
        }
        let version = opts.apiVersion || import.meta.env.VITE_APP_API_VERSION || ''
        if (version) {
            version += '/'
        }
        if (!/^https/.test(config.url)) {
            config.url = (opts.baseUrl || '') + "/" + version + config.url
        }

        if (opts.responseType) config.responseType = opts.responseType
        if (opts.timeout) config.timeout = opts.timeout
        if (opts.onUploadProgress) config.onUploadProgress = opts.onUploadProgress
        try {
            let result = await this.__axios(config)
            return callback(result)
        } catch(e) {
            return callback({ headers: {}, data: { status: 500, msg: e.message || e.msg || e } })
        }
    }

    /**
     * 响应拦截器
     *
     * @param config 配置
     * @param opts 属性
     */
    __response(config, opts) {
        return this.__request(config, opts, response => {
            let res = response?.data ?? {}
            if (res.res === true) {
                return res
            }
            if (res.res === false) {
                this.__error(res.err);
                return
            }
            if (!opts.silence) {
                this.__error(res.msg);
            }
            return res
        })
    }

    /**
     * post方式访问API
     *
     * @param url 路由
     * @param data 参数
     * @param opts 属性
     */
    post(url, data = {}, opts = {}) {
        let _opts = Object.assign({ silence: false, need_token: true, baseUrl: '', apiVersion: '' }, opts)
        let config = {
            method: 'post',
            url,
            data,
            headers: { 'Content-Type': 'application/json;charset=utf-8' }
        }
        return this.__response(config, _opts)
    }

    /**
     * get方式访问API
     *
     * @param url 路由
     * @param params 参数
     * @param opts 属性
     */
    get(url, params = {}, opts) {
        let _opts = Object.assign({ silence: true, need_token: false, baseUrl: '', apiVersion: '' }, opts)
        let config = {
            method: 'get',
            url,
            params,
            headers: { }
        }
        return this.__response(config, _opts)
    }

    /**
     * put方式访问API
     *
     * @param url 路由
     * @param data 参数
     * @param opts 属性
     */
    put(url, data = {}, opts = {}) {
        let _opts = Object.assign({ silence: false, need_token: false, baseUrl: '', apiVersion: '' }, opts)
        let config = {
            method: 'put',
            url,
            data,
            headers: { 'Content-Type': 'application/json;charset=utf-8' }
        }
        return this.__response(config, _opts)
    }

    /**
     * put方式访问API
     *
     * @param url 路由
     * @param data 参数
     * @param opts 属性
     */
    delete(url, data = {}, opts = {}) {
        let _opts = Object.assign({ silence: false, need_token: false, baseUrl: '', apiVersion: '' }, opts)
        let config = {
            method: 'delete',
            url,
            data,
            headers: { 'Content-Type': 'application/json;charset=utf-8' }
        }
        return this.__response(config, _opts)
    }

    /**
     * 上传文件
     *
     * @param url 路由
     * @param data 参数
     * @param opts 属性
     */
    upload(url, data = {}, opts = {}) {
        let _opts = Object.assign({ silence: false, need_token: false, baseUrl: '', apiVersion: '' }, opts);
        let config = {
            method: 'post',
            url,
            headers: { 'Content-Type': 'multipart/form-data' }
        };
        let form = new FormData();
        for (let key in data) {
            if (data[key] instanceof Array) {
                let dataList = data[key];
                for(let i = 0; i < dataList.length; i++) {
                    form.append(key, dataList[i]);
                }
            } else {
                form.append(key, data[key]);
            }
        }
        config.data = form;
        return this.__response(config, _opts)
    }

    /**
     * Download方式访问API
     *
     * @param url 路由
     * @param data 参数
     * @param opts 默认配置
     *    need_token: true: 需要token, false: 不需要token
     *    silence: false: 显示错误消息, true: 不显示错误消息
     *    manual: true: 手动下载, false: 自动下载
     */
    download(url, data = {}, opts) {
        let _opts = Object.assign({ silence: false, need_token: false, manual: false, responseType: 'blob', baseUrl: '', apiVersion: '' }, opts);
        let config = {
            method: 'post',
            url,
            data,
            headers: { 'Content-Type': 'application/json;charset=utf-8' }
        };
        return this.__request(config, _opts, result => {
            let fileName = result.headers['vtuzx-filename'];
            if (fileName) {
                // 下载成功
                let res = { res: true, data: result.data, filename: decodeURIComponent(fileName) }
                if (_opts.manual) {
                    // 手动下载时处理
                    return res
                } else {
                    utils.download(res)
                    return res
                }
            } else {
                // 下载失败
                if (result.request) {
                    return new Promise(resolve => {
                        let reader = new FileReader();
                        reader.onload = e => {
                            let content = JSON.parse(e.target.result);
                            if (content.status != 200 && !_opts.silence) this.__error(content.msg)
                            resolve(content);
                        }
                        reader.readAsText(result.data);
                    })
                } else {
                    if (result.data.status != 200 && !_opts.silence) this.__error(result.data.msg)
                    return result.data
                }
            }
        })
    }
}
